
package nl.hanze.shoestring.ui;

import com.toedter.calendar.JDateChooser;
import com.toedter.components.JSpinField;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import nl.hanze.shoestring.domain.*;
import nl.hanze.shoestring.logic.Logic;
import nl.hanze.shoestring.logic.Rules;
import nl.hanze.shoestring.logic.Utils;

/**
 *  PlanningPanel
 *  PlanningPanel is de GUI waarin de Reizen kunnen worden opgevraagd en bewerkt.
 * 
 * @author henk
 */
public class PlanningPanel extends JPanel {
    private static final long serialVersionUID = 1L;

    Logic logic;
    JPanel pQueryInput, pRecord, pNavigation, pDbGrid;
    JLabel lblZoekSleutel, lblId, lblLand, lblReis_id, lblGids_id, lblBedrag, lblDatum_van, lblDatum_tot;
    JLabel lblAantal_minimum, lblAantal_maximum, lblMin_leeftijd, lblMax_leeftijd;
    JTextField txtZoekSleutel, txtId, txtBedrag;
    JButton butZoeken, butSave, butDelete, butEmpty, butRefresh;
    JComboBox<Object> cmbReis_id, cmbGids_id;
    JSpinField spinAantal_minimum, spinAantal_maximum, spinMin_leeftijd, spinMax_leeftijd;
    JDateChooser calDatum_van, calDatum_tot;
    JTable table;
    JScrollPane scrollPaneRes;
    DefaultTableModel model;
    Planning planningObj=null;
    List<Planning> planningList;

    int heightField = 25;
    int numberOfRows = 14;

    public PlanningPanel(Logic logic) {
        this.logic = logic;
        
        table = new JTable();
        setLayout(new BorderLayout(20, 20));

        // zoek optie  north sectie
        pQueryInput = new JPanel();
        pQueryInput.setLayout(null);
        pQueryInput.setPreferredSize(new Dimension(400, 40));

        lblZoekSleutel = UIHelper.createLabel(lblZoekSleutel = new JLabel(), "Zoeksleutel", 20, 10, 150, heightField, pQueryInput);
        txtZoekSleutel = UIHelper.createTextField(txtZoekSleutel = new JTextField(), "", 170, 10, 300, heightField, pQueryInput);
        txtZoekSleutel.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                searchPlanning();
            }
            
        });
        
        butZoeken = UIHelper.createButton(butZoeken = new JButton(), "Zoeken", 480, 10, 100, heightField, pQueryInput);
        butZoeken.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        searchPlanning();
                    }
                });

        // Center sectie, database record detail
        pRecord = new JPanel();
        pRecord.setLayout(null);
        pRecord.setPreferredSize(new Dimension(400, 500));
        pRecord.setBorder(BorderFactory.createLineBorder(Color.blue));
        
        lblId = UIHelper.createLabel(lblId = new JLabel(), "Nummer", 20, 10, 150, heightField, pRecord);
        txtId = UIHelper.createTextField(txtId = new JTextField(), "", 170, 10, 100, heightField, pRecord);

        lblReis_id = UIHelper.createLabel(lblReis_id = new JLabel(), "Reis", 20, 40, 150, heightField, pRecord);
        cmbReis_id = UIHelper.createCombo(cmbReis_id = new JComboBox<Object>(), 170, 40, 300, heightField, pRecord);
        

        lblBedrag = UIHelper.createLabel(lblBedrag = new JLabel(), "Bedrag", 20, 70, 150, heightField, pRecord);
        txtBedrag = UIHelper.createTextField(txtBedrag = new JTextField(), "", 170, 70, 300, heightField, pRecord);

        lblDatum_van = UIHelper.createLabel(lblDatum_van = new JLabel(), "Begindatum", 20, 100, 150, heightField, pRecord);
        calDatum_van = UIHelper.createDateChooser(calDatum_van = new JDateChooser(), null, 170, 100, 150, heightField, pRecord);
        // 
            calDatum_van.getDateEditor().addPropertyChangeListener(
                new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent e) {
                    if ("date".equals(e.getPropertyName())) {
                        validatePlanningDuurAndGids(e);
                    }
                }
            });
        
        lblDatum_tot = UIHelper.createLabel(lblDatum_tot = new JLabel(), "Einddatum", 20, 130, 150, heightField, pRecord);
        calDatum_tot = UIHelper.createDateChooser(calDatum_tot = new JDateChooser(), null, 170, 130, 150, heightField, pRecord);
        
        lblAantal_minimum = UIHelper.createLabel(lblAantal_minimum = new JLabel(), "Minimum aantal", 20, 160, 150, heightField, pRecord);
        spinAantal_minimum = UIHelper.createSpinField(spinAantal_minimum = new JSpinField(), 0, 170, 160, 150, heightField, pRecord, SwingConstants.LEFT);

        lblAantal_maximum = UIHelper.createLabel(lblAantal_maximum = new JLabel(), "Maximum aantal", 20, 190, 150, heightField, pRecord);
        spinAantal_maximum = UIHelper.createSpinField(spinAantal_maximum = new JSpinField(), 0, 170, 190, 150, heightField, pRecord, SwingConstants.LEFT);

        lblMin_leeftijd = UIHelper.createLabel(lblMin_leeftijd = new JLabel(), "Minimum leeftijd", 20, 220, 150, heightField, pRecord);
        spinMin_leeftijd = UIHelper.createSpinField(spinMin_leeftijd = new JSpinField(), 0, 170, 220, 150, heightField, pRecord, SwingConstants.LEFT);

        lblMax_leeftijd = UIHelper.createLabel(lblMax_leeftijd = new JLabel(), "Maximum leeftijd", 20, 250, 150, heightField, pRecord);
        spinMax_leeftijd = UIHelper.createSpinField(spinMax_leeftijd = new JSpinField(), 0, 170, 250, 150, heightField, pRecord, SwingConstants.LEFT);

        lblGids_id = UIHelper.createLabel(lblGids_id = new JLabel(), "Gids", 20, 280, 150, heightField, pRecord);
        cmbGids_id = UIHelper.createCombo(cmbGids_id = new JComboBox<Object>(), 170, 280, 300, heightField, pRecord);



        // fill combobox with table data
        fillComboReis();
        fillComboMedewerker();
        
                butSave = UIHelper.createButton(butSave = new JButton(), "Opslaan", 170, 320, 120, heightField, pRecord);
                butSave.addActionListener(
                        new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                System.out.println("save");
                                if(planningObj!=null) {
                                    updateRecord(planningObj);
                                } else {
                                    addRecord();
                                }
                            }
                        });


                butDelete = UIHelper.createButton(butDelete = new JButton(), "Verwijderen", 350, 320, 120, heightField, pRecord);
                butDelete.addActionListener(
                        new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                System.out.println("delete");
                                if(planningObj!=null) {
                                    deleteRecord(planningObj);
                                }
                        }});

                butEmpty = UIHelper.createButton(butDelete = new JButton(), "Leeg/Nieuw", 350, 10, 120, heightField, pRecord);
                butEmpty.addActionListener(
                        new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                emptyAll();
                        }});

        // refresh combobox Reizen
        butRefresh = UIHelper.createButton(butRefresh = new JButton(), "", 480, 40, 30, heightField, pRecord);
        butRefresh.setIcon(new ImageIcon("src/nl/hanze/shoestring/ui/graphics/refresh.png"));
        butRefresh.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        fillComboReis();
                }});

        pRecord.add(butSave);
        pRecord.add(butDelete);
        pRecord.add(butEmpty);
        pRecord.add(butRefresh);
        
        // fill tab pane
        add(pRecord, BorderLayout.CENTER);
        add(pQueryInput, BorderLayout.NORTH);
        addTable();
        emptyAll();
    }

    /**
     * Haal informatie uit database en toon in JTable
     */
    private void addTable() {

        // Gridcontainer
        pDbGrid = new JPanel(new BorderLayout(2, 3));

        // scroll pane eigenschappen
        scrollPaneRes = new JScrollPane(table);
        Dimension d = table.getPreferredSize();
        scrollPaneRes.setPreferredSize(new Dimension(d.width, table.getRowHeight() * numberOfRows));

        // navigatie container
        UIHelper.addNavigation(pNavigation = new JPanel(), table, scrollPaneRes, numberOfRows);
        
        // kolom eigenschappen - breedte
        Object[] headers = {"Nummer", "Reis", "Gids", "Bedrag", "Begindatum", "Einddatum", "Min#", "Max#", "MinLft", "MaxLft" };
        int[] breedte = {60, 300, 130, 100, 100, 100, 50, 50, 50, 50};
        
        // tablemodel en eigenschappen instellen, kolombreedte etc
        model = new DefaultTableModel(headers, 0) {

            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
            
            // rendering van cellen, toont checkbox en juiste datum indien datatype overeenkomstig is
            // null velden veroorzaken fout, standaard maar op String gezet....
            @Override
            public Class getColumnClass(int column){
                try {
                 return getValueAt(0, column).getClass();
                } catch (java.lang.NullPointerException e) {
                    return String.class;
                }
            }
        };

        table.setModel(model);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        for (int i0 = 0; i0 < breedte.length; i0++) {
            table.getColumnModel().getColumn(i0).setPreferredWidth(breedte[i0]);
        }
        
        updateTable(true);

        // selecteer row door muisklik    
        table.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                planningObj = planningList.get(table.convertRowIndexToModel(table.getSelectedRow()));
                getRecord(planningObj);
            }
        });

        pDbGrid.add(scrollPaneRes, BorderLayout.CENTER);
        pDbGrid.add(pNavigation, BorderLayout.SOUTH);
        add(pDbGrid, BorderLayout.SOUTH);
    }
    
    /**
     *  Vul Combobox met Reizen
     *  Refresh mogelijk
     */
    private void fillComboReis() {
        List<Reis> reis = logic.getReisList();
        Collections.sort(reis);
        cmbReis_id.setModel(new DefaultComboBoxModel(reis.toArray()));
    }
    
    /**
     *  Vul Combobox met Medewerkers
     *  Rule P006 beperkt de selectie, Gids kan niet tegelijkertijd meerdere reizen begeleiden
     */
    private void fillComboMedewerker() {
        List<Medewerker> medewerker = logic.getMedewerkerList(true);
        if(calDatum_van.getDate()!=null && calDatum_tot.getDate()!=null) {
            for(Iterator<Medewerker> mw = medewerker.iterator(); mw.hasNext();) {
                if( planningObj==null) {
                    if(!Rules.checkGidsBeschikbaar(mw.next(), calDatum_van.getDate(), calDatum_tot.getDate())) {
                        mw.remove();
                    }
                } else {
                    if(!Rules.checkGidsBeschikbaar(mw.next(), planningObj)) {
                        mw.remove();
                    }
                }
            }
        }
        if(medewerker!=null && medewerker.size()>0) {
            cmbGids_id.setModel(new DefaultComboBoxModel(medewerker.toArray()));
        } else {
            Utils.errorMessage(this, "Geen gids beschikbaar", "Er is geen gids beschikbaar in dit tijdvak");
        }
            
    }
        
    
    /*
     *  Vul detailvelden met geselecteerde rowdata  
     */
    private void getRecord(Planning planningObj) {
        txtId.setText("" + planningObj.getId());
        txtId.setEditable(false);
        cmbReis_id.setSelectedItem(planningObj.getReisId());
        cmbGids_id.setSelectedItem(planningObj.getGidsId());
        txtBedrag.setText("" + planningObj.getBedrag());
        calDatum_van.setDate(planningObj.getDatumVan());
        calDatum_tot.setDate(planningObj.getDatumTot());
        spinAantal_minimum.setValue(planningObj.getAantalMinimum());
        spinAantal_maximum.setValue(planningObj.getAantalMaximum());
        spinMin_leeftijd.setValue(planningObj.getMinimumLeeftijd());
        spinMax_leeftijd.setValue(planningObj.getMaximumLeeftijd());
    }  
 
   
    
    /*
     *  update record  
     */
    private void updateRecord(Planning planningObj) {
        planningObj.setReisId((Reis) cmbReis_id.getModel().getSelectedItem());
        planningObj.setGidsId((Medewerker) cmbGids_id.getModel().getSelectedItem());
        planningObj.setBedrag(Utils.getFloatValueOrNull(txtBedrag.getText()));
        planningObj.setDatumVan(calDatum_van.getDate());
        planningObj.setDatumTot(calDatum_tot.getDate());
        planningObj.setAantalMinimum(spinAantal_minimum.getValue());
        planningObj.setAantalMaximum(spinAantal_maximum.getValue());
        planningObj.setMinimumLeeftijd(spinMin_leeftijd.getValue());
        planningObj.setMaximumLeeftijd(spinMax_leeftijd.getValue());
        logic.updatePlanning(planningObj);
        updateTable(true);
        emptyAll();
    }
    
    /*
     *  add new record  
     */
    private void addRecord() {
        planningObj = new Planning();
        planningObj.setReisId((Reis) cmbReis_id.getModel().getSelectedItem());
        planningObj.setGidsId((Medewerker) cmbGids_id.getModel().getSelectedItem());
        planningObj.setBedrag(Utils.getFloatValueOrNull(txtBedrag.getText()));
        planningObj.setDatumVan(calDatum_van.getDate());
        planningObj.setDatumTot(calDatum_tot.getDate());
        planningObj.setAantalMinimum(spinAantal_minimum.getValue());
        planningObj.setAantalMaximum(spinAantal_maximum.getValue());
        planningObj.setMinimumLeeftijd(spinMin_leeftijd.getValue());
        planningObj.setMaximumLeeftijd(spinMax_leeftijd.getValue());
        logic.addPlanning(planningObj);
        updateTable(true);        
        emptyAll();
    }

    /*
     *  delete record  
     */
    private void deleteRecord(Planning planningObj) {
        logic.deletePlanning(planningObj);
        updateTable(true);
        emptyAll();
    }
    
    /*
     *  maak velden leeg en planningtypeObj =null  
     */
    private void emptyAll() {
        txtId.setText("");
        txtId.setEditable(false);
        cmbReis_id.setSelectedItem(null);
        cmbGids_id.setSelectedItem(null);
        txtBedrag.setText("");
        calDatum_van.setDate(Utils.getDateOfTomorrow());
        calDatum_van.setMinSelectableDate(Utils.getDateOfTomorrow());
        calDatum_tot.setDate(null);
        spinAantal_minimum.setValue(0);
        spinAantal_maximum.setValue(0);
        spinMin_leeftijd.setValue(0);
        spinMax_leeftijd.setValue(100);
        calDatum_tot.setEnabled(true);
        // referentie leeg
        planningObj=null;
    }

    private void searchPlanning(){
        planningList = logic.searchPlanning(txtZoekSleutel.getText(), null, null);
        updateTable(false);
    }
    
    
    private void updateTable(Boolean refresh) {
        if(refresh) {
            planningList = logic.getPlanningList();
        }

        model.setRowCount(0);
        // data in JTable plaatsen
        for (Planning Planning : planningList) {
            Object[] o = {Planning.getId(),
                Planning.getReisId().getNaam(),
                Planning.getGidsId().getPersoon().getAchternaam(),
                Planning.getBedrag(),
                Planning.getDatumVan(),
                Planning.getDatumTot(),
                Planning.getAantalMinimum(),
                Planning.getAantalMaximum(),
                Planning.getMinimumLeeftijd(),
                Planning.getMaximumLeeftijd(),
                    };
            model.addRow(o);
        }
    }
    
    /*
     *  Validatie Reisduur en beschikbaarheid gids
     *  P002 en P003 
     */
    private void validatePlanningDuurAndGids(PropertyChangeEvent e) {
        Reis reis = (Reis) cmbReis_id.getModel().getSelectedItem();
        if(reis!=null) {
            Calendar cal = Calendar.getInstance();
            cal.setTime((Date) e.getNewValue());
            cal.add(Calendar.DAY_OF_MONTH, reis.getDuur());
            calDatum_tot.setDate(cal.getTime());
            calDatum_tot.setEnabled(false);
            cmbGids_id.removeAllItems();
            fillComboMedewerker();
        }
    }
    
    /**
     * Invoercontrole Reserveringscherm
     * @return 
     */
    private Boolean isInputOk() {
        
        return true;
    }

}

